package br.com.roteador.rota;

import java.lang.reflect.InvocationTargetException;
import java.util.Date;
import java.util.ResourceBundle;

import javax.annotation.PostConstruct;
import javax.inject.Inject;

import org.apache.commons.beanutils.BeanUtils;

import br.com.caelum.vraptor.Consumes;
import br.com.caelum.vraptor.Controller;
import br.com.caelum.vraptor.Get;
import br.com.caelum.vraptor.Path;
import br.com.caelum.vraptor.Post;
import br.com.caelum.vraptor.Result;
import br.com.caelum.vraptor.view.Results;
import br.com.roteador.component.AcessSession;
import br.com.roteador.component.StringUteis;
import br.com.roteador.controller.BasicController;
import br.com.roteador.endereco.Endereco;
import br.com.roteador.endereco.EnderecoDAO;
import br.com.roteador.localizacao.LocalizacaoDAO;
import br.com.roteador.motorista.Motorista;
import br.com.roteador.motorista.MotoristaDAO;

@Controller
public class RotaController extends BasicController {
	@Inject private RotaDAO rotaDAO;
	@Inject private MotoristaDAO motoristaDAO;
	@Inject private EnderecoDAO enderecoDAO;
	@Inject private LocalizacaoDAO localizacaoDAO; 

	 @Inject
	public RotaController(Result result, ResourceBundle bundle,
			RotaDAO rotaDAO, MotoristaDAO motoristaDAO, 
			EnderecoDAO enderecoDAO, AcessSession session) {
		 this.result = result;
		this.bundle = bundle;
		this.rotaDAO = rotaDAO;
		this.session = session;
		this.motoristaDAO = motoristaDAO;
		this.enderecoDAO = enderecoDAO;
	}
	 
	 @PostConstruct
    private void init(){
    	injetaUsuario();
    }
    
    public RotaController(){}
    
    @Path(value = "/" + ROTA)
    @Get
    public void rota() {
        result.include("listaRotas", rotaDAO.recuperaRotas());
    }
    
    @Path(value = "/" + ROTA + "/" + NOVO)
    @Get
    public void novo() {
    	result.include("listaMotoristas", motoristaDAO.recuperaMotoristas());
    	result.include("listaEnderecos", enderecoDAO.recuperaEnderecos());
        result.include("rota", new Rota());
    }
    
    @Path(value = "/" + ROTA + "/" + EDITAR)
    @Post
    public void editar(String id){
    	if(!StringUteis.isEmpty(id)){
    		Rota rota = (Rota) rotaDAO.find(Rota.class, Integer.parseInt(id));
    		result.include("listaMotoristas", motoristaDAO.recuperaMotoristas());
        	result.include("listaEnderecos", enderecoDAO.recuperaEnderecos());
	        result.include(ROTA, rota);
    	} else {
    		mensagemErro("erro.ao.recuperar");
    	}
    }
    
    @Path(value = "/" + ROTA + "/posicoes/{id}")
    @Get
    public void posicoes(String id){
    	if(!StringUteis.isEmpty(id)){
    		Rota rota = (Rota) rotaDAO.find(Rota.class, Integer.parseInt(id));
    		result.include("listaPosicoes", localizacaoDAO.recuperaPosicoes(rota.getMotorista().getImei(), rota.getDataInicio(), rota.getDataFim()));
    	} else {
    		mensagemErro("erro.ao.recuperar");
    	}
    }
    
    @Consumes("application/json")
    @Path(value = "/" + ROTA + "/recuperaRotaAtual")
    @Post
    public void recuperaRotaAtualPorMotorias(Motorista motorista){
    	motorista = motoristaDAO.recuperaMotoristaPorNome(motorista.getNome());
    	if(motorista != null){
	   		Rota rotas = rotaDAO.recuperaRotaAtualPorMotorista(motorista);
	   		if(rotas != null){
		   		rotas.getEnderecos();
		   		rotas.setUsuario(null);
		   		rotas.setDataGravacao(null);
		   		rotas.setId(null);
		   		rotas.setMotorista(null);
		   		for(Endereco end : rotas.getEnderecos()){
		   			end.setId(null);
		   			end.setUsuario(null);
		   			end.setDestinos(null);
		   			end.setDataGravacao(null);
		   		}
		    	result.use(Results.json()).withoutRoot().from(rotas).recursive().serialize();
	   		} else {
	   			result.use(Results.json()).withoutRoot().from(false).serialize();
	   		}
    	}else{
    		result.use(Results.json()).withoutRoot().from(false).serialize();
    	}
    }
    
    @Path(value = "/" + ROTA + "/" + EXCLUIR)
    @Post
    public void excluir(String id){
    	if(!StringUteis.isEmpty(id)){
    		Rota rota = (Rota) rotaDAO.find(Rota.class, Integer.parseInt(id));
    		rotaDAO.remove(rota);
    		result.include("listaMotoristas", motoristaDAO.recuperaMotoristas());
        	result.include("listaEnderecos", enderecoDAO.recuperaEnderecos());
        	mensagemSucesso("rota.excluida.sucesso");
    	} else {
    		mensagemErro("erro.ao.recuperar");
    	}
    	redirect();
    }

    @Post
	public void gravar(Rota rota) {
		if(rota != null){
    		if(null == rota.getMotorista() || null == rota.getMotorista()){
    			mensagemErro("erro.motorista.obrigatorio");
    		}
    		if(null == rota.getDataInicio()){
    			mensagemErro("erro.data.inicio.obrigatorio");
    		}
    		if(null == rota.getDataFim()){
    			mensagemErro("erro.data.fim.obrigatorio");
    		}
    		if(null == rota.getEnderecos()){
    			mensagemErro("erro.endereco.obrigatorio");
    		}
    		if(resultPossui(ERROR) && resultPossuiConteudo(ERROR)){ redirect(); return;}
    		Rota pre = rotaDAO.recuperaRotaPorMotoristaDataInicioFim(rota.getDataInicio(), rota.getDataFim(), rota.getMotorista());
	        if(pre != null){
	        	if(rota.getId() != null){
		        	/* Se o id dos 2 rotas forem diferentes
		        	 * */
		        	if(pre.getId() != rota.getId()){
		        		mensagemErro("erro.rota.existe");
		        	}else{
		        		try {
			                BeanUtils.copyProperties(pre, rota);
			            } catch (IllegalAccessException e) {
			            	mensagemErro("erro.ao.gravar");
			            } catch (InvocationTargetException e) {
			            	mensagemErro("erro.ao.gravar");
			            }
			            rotaDAO.update(pre);
			            mensagemSucesso("rota.atualizado.sucesso");
		        	}
		        } else {
		        	mensagemErro("erro.rota.existe");
		        } 
	        } else {
	        	if(rota.getId() != null){
	        		pre = (Rota) rotaDAO.find(Rota.class, rota.getId());
	        		Date data = pre.getDataGravacao();
	        		try {
		                BeanUtils.copyProperties(pre, rota);
		            } catch (IllegalAccessException e) {
		            	mensagemErro("erro.ao.gravar");
		            } catch (InvocationTargetException e) {
		            	mensagemErro("erro.ao.gravar");
		            }
	        		pre.setDataGravacao(data);
	        		pre.setUsuario(session.getUsuario());
	        		rotaDAO.update(pre);
	        		mensagemSucesso("rota.atualizado.sucesso");
	        	} else {
	        		rota.setUsuario(session.getUsuario());
		        	rota.setDataGravacao(new Date());
		            rotaDAO.save(rota);
		            mensagemSucesso("rota.gravado.sucesso");
	        	}
	        }
    	} else {
    		mensagemErro("erro.ao.gravar");
    	}
        redirect();
	}

	@Override
	protected void redirect() {
		result.redirectTo(RotaController.class).rota();
	}

}